package org.test.netty;
import java.net.InetSocketAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * 使用netty构建websocket服务器
 */
@Component
public class NettyWebSocketServer implements Runnable{
	
	private static final Logger log = LoggerFactory.getLogger(NettyWebSocketServer.class);
	//诊断服务器端口
	private  int port;
	
	public NettyWebSocketServer(int port) throws InterruptedException {
		this.port = port;
	}
	
	public NettyWebSocketServer() {
	}

	@Override
	public void run(){
		// 引导辅助程序
		ServerBootstrap b = new ServerBootstrap();
		//守护线程组
		EventLoopGroup bossGroup = new NioEventLoopGroup(); 
		//工作线程组
	    EventLoopGroup workerGroup = new NioEventLoopGroup();
		  b.group(bossGroup,workerGroup);
		 // 设置nio类型的channel
		  b.channel(NioServerSocketChannel.class);
		  b.option(ChannelOption.SO_BACKLOG, 2048);
		 // 设置监听端口
	      b.localAddress(new InetSocketAddress(port));
	      
	  	//有连接到达时会创建一个channel
	      b.childHandler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel ch) throws Exception {
				ch.pipeline().addLast("http-codec",new HttpServerCodec());
				ch.pipeline().addLast("aggregator",new  HttpObjectAggregator(65536));
				ch.pipeline().addLast("http-chunked",new ChunkedWriteHandler());
				// pipeline管理channel中的Handler，在channel队列中添加一个handler来处理业务
				ch.pipeline().addLast("myHandler",new WebsocketServerHandler());
			}
		}).childOption(ChannelOption.SO_KEEPALIVE, true);
	      
	   // 配置完成，开始绑定server，通过调用sync同步方法阻塞直到绑定成功
	      try {
			ChannelFuture f = b.bind().sync();
			log.info(NettyWebSocketServer.class.getName() + " started and listen on " + f.channel().localAddress());
			// 应用程序会一直等待，直到channel关闭
			f.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
			
		}finally{
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}


}
